﻿using Caliburn.Micro;
using Microsoft.Win32;
using SD.Common;
using SD.Infrastructure.DTOBase;
using SD.Infrastructure.WPF.Caliburn.Aspects;
using SD.Infrastructure.WPF.Caliburn.Base;
using SD.Infrastructure.WPF.Extensions;
using SD.Infrastructure.WPF.Interfaces;
using SD.Infrastructure.WPF.Models;
using SD.IOC.Core.Mediators;
using SD.Toolkits.Excel;
using SlamDunk.MES.Client.ViewModels.Facility;
using SlamDunk.MES.IAppService.DTOs.Outputs.MaintenanceContext;
using SlamDunk.MES.IAppService.Interfaces;
using SlamDunk.MES.Presentation;
using SlamDunk.MES.Presentation.Maps;
using SlamDunk.MES.Presentation.Models.ExportModels;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.ServiceModel.Extensions;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;

namespace SlamDunk.MES.Client.ViewModels.EquipmentMaintenance
{
    /// <summary>
    /// 设备维护记录首页视图模型
    /// </summary>
    public class IndexViewModel : ScreenBase, IPaginatable
    {
        #region # 字段及构造器

        /// <summary>
        /// 维护管理服务契约接口代理
        /// </summary>
        private readonly ServiceProxy<IMaintenanceContract> _maintenanceContract;

        /// <summary>
        /// 窗口管理器
        /// </summary>
        private readonly IWindowManager _windowManager;

        /// <summary>
        /// 依赖注入构造器
        /// </summary>
        public IndexViewModel(ServiceProxy<IMaintenanceContract> maintenanceContract, IWindowManager windowManager)
        {
            this._maintenanceContract = maintenanceContract;
            this._windowManager = windowManager;

            //默认值
            this.PageIndex = 1;
            this.PageSize = 20;
        }

        #endregion

        #region # 属性

        #region 关键字 —— string Keywords
        /// <summary>
        /// 关键字
        /// </summary>
        [DependencyProperty]
        public string Keywords { get; set; }
        #endregion

        #region 开始时间 —— DateTime? StartTime
        /// <summary>
        /// 开始时间
        /// </summary>
        [DependencyProperty]
        public DateTime? StartTime { get; set; }
        #endregion

        #region 结束时间 —— DateTime? EndTime
        /// <summary>
        /// 结束时间
        /// </summary>
        [DependencyProperty]
        public DateTime? EndTime { get; set; }
        #endregion

        #region 页码 —— int PageIndex
        /// <summary>
        /// 页码
        /// </summary>
        [DependencyProperty]
        public int PageIndex { get; set; }
        #endregion

        #region 页容量 —— int PageSize
        /// <summary>
        /// 页容量
        /// </summary>
        [DependencyProperty]
        public int PageSize { get; set; }
        #endregion

        #region 总记录数 —— int RowCount
        /// <summary>
        /// 总记录数
        /// </summary>
        [DependencyProperty]
        public int RowCount { get; set; }
        #endregion

        #region 总页数 —— int PageCount
        /// <summary>
        /// 总页数
        /// </summary>
        [DependencyProperty]
        public int PageCount { get; set; }
        #endregion

        #region 已选设备维护类 —— EquipmentMaintainClassInfo SelectedEquipmentMaintainClass
        /// <summary>
        /// 已选设备维护类
        /// </summary>
        [DependencyProperty]
        public EquipmentMaintainClassInfo SelectedEquipmentMaintainClass { get; set; }
        #endregion

        #region 已选设备资产 —— EquipmentAssetInfo SelectedEquipmentAsset
        /// <summary>
        /// 已选设备资产
        /// </summary>
        [DependencyProperty]
        public EquipmentAssetInfo SelectedEquipmentAsset { get; set; }
        #endregion

        #region 已选工厂模型 —— Node SelectedFacility
        /// <summary>
        /// 已选工厂模型
        /// </summary>
        [DependencyProperty]
        public Node SelectedFacility { get; set; }
        #endregion

        #region 设备维护记录列表 —— ObservableCollection<Wrap<EquipmentMaintenanceInfo>> EquipmentMaintenances
        /// <summary>
        /// 设备维护记录列表
        /// </summary>
        [DependencyProperty]
        public ObservableCollection<Wrap<EquipmentMaintenanceInfo>> EquipmentMaintenances { get; set; }
        #endregion

        #region 设备维护类列表 —— ObservableCollection<EquipmentMaintainClassInfo> EquipmentMaintainClasses
        /// <summary>
        /// 设备维护类列表
        /// </summary>
        [DependencyProperty]
        public ObservableCollection<EquipmentMaintainClassInfo> EquipmentMaintainClasses { get; set; }
        #endregion

        #region 设备资产列表 —— ObservableCollection<EquipmentAssetInfo> EquipmentAssets
        /// <summary>
        /// 设备资产列表
        /// </summary>
        [DependencyProperty]
        public ObservableCollection<EquipmentAssetInfo> EquipmentAssets { get; set; }
        #endregion

        #endregion

        #region # 方法

        //Initializations

        #region 初始化 —— override async Task OnInitializeAsync(CancellationToken cancellationToken)
        /// <summary>
        /// 初始化
        /// </summary>
        protected override async Task OnInitializeAsync(CancellationToken cancellationToken)
        {
            IEnumerable<EquipmentMaintainClassInfo> equipmentMaintainClasses = await Task.Run(() => this._maintenanceContract.Channel.GetEquipmentMaintainClassesByPage(null, null, 1, int.MaxValue).Datas, cancellationToken);
            IEnumerable<EquipmentAssetInfo> equipmentAssets = await Task.Run(() => this._maintenanceContract.Channel.GetEquipmentAssetsByPage(null, null, null, null, 1, int.MaxValue).Datas, cancellationToken);
            this.EquipmentMaintainClasses = new ObservableCollection<EquipmentMaintainClassInfo>(equipmentMaintainClasses);
            this.EquipmentAssets = new ObservableCollection<EquipmentAssetInfo>(equipmentAssets);

            await this.ReloadEquipmentMaintenances();
        }
        #endregion


        //Actions

        #region 选择工厂模型 —— async void SelectFacility()
        /// <summary>
        /// 选择工厂模型
        /// </summary>
        public async void SelectFacility()
        {
            this.Busy();

            SelectFacilityViewModel viewModel = ResolveMediator.Resolve<SelectFacilityViewModel>();
            bool? result = await this._windowManager.ShowDialogAsync(viewModel);
            if (result == true)
            {
                this.SelectedFacility = viewModel.SelectedFacility;
            }

            this.Idle();
        }
        #endregion

        #region 清空工厂模型 —— void ClearFacility()
        /// <summary>
        /// 清空工厂模型
        /// </summary>
        public void ClearFacility()
        {
            this.SelectedFacility = null;
        }
        #endregion

        #region 加载设备维护记录列表 —— async void LoadEquipmentMaintenances()
        /// <summary>
        /// 加载设备维护记录列表
        /// </summary>
        public async void LoadEquipmentMaintenances()
        {
            await this.ReloadEquipmentMaintenances();
        }
        #endregion

        #region 创建设备维护记录 —— async void CreateEquipmentMaintenance()
        /// <summary>
        /// 创建设备维护记录
        /// </summary>
        public async void CreateEquipmentMaintenance()
        {
            AddViewModel viewModel = ResolveMediator.Resolve<AddViewModel>();
            await viewModel.Load(this.EquipmentMaintainClasses, this.EquipmentAssets);
            bool? result = await this._windowManager.ShowDialogAsync(viewModel);
            if (result == true)
            {
                await this.ReloadEquipmentMaintenances();
            }
        }
        #endregion

        #region 修改设备维护记录 —— async void UpdateEquipmentMaintenance()
        /// <summary>
        /// 修改设备维护记录
        /// </summary>
        public async void UpdateEquipmentMaintenance()
        {
            #region # 验证

            if (this.EquipmentMaintenances.Count(x => x.IsChecked == true) != 1)
            {
                MessageBox.Show("请勾选一条要修改的设备维护记录！", "警告", MessageBoxButton.OK, MessageBoxImage.Warning);
                return;
            }

            #endregion

            Wrap<EquipmentMaintenanceInfo> equipmentAsset = this.EquipmentMaintenances.Single(x => x.IsChecked == true);

            this.Busy();

            UpdateViewModel viewModel = ResolveMediator.Resolve<UpdateViewModel>();
            viewModel.Load(equipmentAsset.Model);
            bool? result = await this._windowManager.ShowDialogAsync(viewModel);

            this.Idle();

            if (result == true)
            {
                await this.ReloadEquipmentMaintenances();
            }
        }
        #endregion

        #region 删除设备维护记录 —— async void RemoveEquipmentMaintenances()
        /// <summary>
        /// 删除设备维护记录
        /// </summary>
        public async void RemoveEquipmentMaintenances()
        {
            #region # 加载勾选

            EquipmentMaintenanceInfo[] checkedEquipmentMaintenances = this.EquipmentMaintenances.Where(x => x.IsChecked == true).Select(x => x.Model).ToArray();
            if (!checkedEquipmentMaintenances.Any())
            {
                MessageBox.Show("请勾选要删除的设备维护记录！", "警告", MessageBoxButton.OK, MessageBoxImage.Warning);
                return;
            }

            #endregion

            MessageBoxResult result = MessageBox.Show("确定要删除吗？", "警告", MessageBoxButton.YesNo, MessageBoxImage.Warning);
            if (result == MessageBoxResult.Yes)
            {
                this.Busy();

                IMaintenanceContract maintenanceContract = this._maintenanceContract.Channel;
                await Task.Run(() => checkedEquipmentMaintenances.ForEach(authority => maintenanceContract.RemoveEquipmentMaintenance(authority.Id)));
                await this.ReloadEquipmentMaintenances();

                this.Idle();
            }
        }
        #endregion

        #region 打印设备维护记录 —— async void PrintEquipmentMaintenances()
        /// <summary>
        /// 打印设备维护记录
        /// </summary>
        public async void PrintEquipmentMaintenances()
        {
            #region # 验证

            if (this.EquipmentMaintenances.All(x => x.IsChecked != true))
            {
                MessageBox.Show("请勾选至少一条要打印的设备维护记录！", "警告", MessageBoxButton.OK, MessageBoxImage.Warning);
                return;
            }

            #endregion

            IEnumerable<Wrap<EquipmentMaintenanceInfo>> checkedWraps = this.EquipmentMaintenances.Where(x => x.IsChecked == true);

            this.Busy();

            PrintViewModel viewModel = ResolveMediator.Resolve<PrintViewModel>();
            viewModel.Load(checkedWraps.Select(x => x.Model));
            await this._windowManager.ShowDialogAsync(viewModel);

            this.Idle();
        }
        #endregion

        #region 导出设备维护记录 —— async void ExportEquipmentMaintenances()
        /// <summary>
        /// 导出设备维护记录
        /// </summary>
        public async void ExportEquipmentMaintenances()
        {
            PageModel<EquipmentMaintenanceInfo> pageModel = await Task.Run(() => this._maintenanceContract.Channel.GetEquipmentMaintenancesByPage(this.Keywords, this.SelectedEquipmentMaintainClass?.Id, null, this.SelectedEquipmentAsset?.Id, this.StartTime, this.EndTime, this.SelectedFacility?.Id, 1, int.MaxValue));

            EquipmentMaintenanceEm[] equipmentMaintenanceEms = pageModel.Datas.Select(x => x.ToExportView()).ToArray();
            if (!equipmentMaintenanceEms.Any())
            {
                MessageBox.Show("导出数据为空，不能进行导出！", "警告", MessageBoxButton.OK, MessageBoxImage.Warning);
                return;
            }
            SaveFileDialog saveFileDialog = new SaveFileDialog
            {
                Filter = Constants.ExeclFileExtensionsFilter,
                FileName = $"设备维护记录_{DateTime.Now.ToString(Constants.ExportFileTimeFormat)}",
                AddExtension = true,
                RestoreDirectory = true
            };
            if (saveFileDialog.ShowDialog() == true)
            {
                string filePath = saveFileDialog.FileName;
                ExcelWriter.WriteFile(equipmentMaintenanceEms, filePath);
            }
        }
        #endregion

        #region 全选 —— void CheckAll()
        /// <summary>
        /// 全选
        /// </summary>
        public void CheckAll()
        {
            this.EquipmentMaintenances.ForEach(x => x.IsChecked = true);
        }
        #endregion

        #region 取消全选 —— void UncheckAll()
        /// <summary>
        /// 取消全选
        /// </summary>
        public void UncheckAll()
        {
            this.EquipmentMaintenances.ForEach(x => x.IsChecked = false);
        }
        #endregion


        //Private

        #region 加载设备维护记录列表 —— async Task ReloadEquipmentMaintenances()
        /// <summary>
        /// 加载设备维护记录列表
        /// </summary>
        private async Task ReloadEquipmentMaintenances()
        {
            this.Busy();

            PageModel<EquipmentMaintenanceInfo> pageModel = await Task.Run(() => this._maintenanceContract.Channel.GetEquipmentMaintenancesByPage(this.Keywords, this.SelectedEquipmentMaintainClass?.Id, null, this.SelectedEquipmentAsset?.Id, this.StartTime, this.EndTime, this.SelectedFacility?.Id, this.PageIndex, this.PageSize));
            this.RowCount = pageModel.RowCount;
            this.PageCount = pageModel.PageCount;

            IEnumerable<Wrap<EquipmentMaintenanceInfo>> wrapModels = pageModel.Datas.Select(x => x.Wrap());
            this.EquipmentMaintenances = new ObservableCollection<Wrap<EquipmentMaintenanceInfo>>(wrapModels);

            this.Idle();
        }
        #endregion

        #endregion
    }
}
